Skip navigation and go to content

CSS Visibility Techniques in the CampSpots Component Sandbox

On this page

Introducing the CampSpots Component Sandbox

There’s a bonus Component Sandbox page in our CampSpots app that contains a few small examples of common components for experimentation.

Bookmark http://localhost:1234/component-sandbox, as we’ll revisit it throughout the workshop.

For now, we’re going to look at how different CSS visibility techniques affect a button.

CSS Visibility Techniques

The CSS Visibility Techniques section of the sandbox has a “Reserve” button above radio buttons that will apply different hiding methods to it.

The CSS Visibility Techniques section of the Component Sandbox

💡Tip

Remember, the button element is superior to a div! They’re focusable, have an implicit button role and can respond to click events without additional keyboard events.

Examining the Accessibility Tree in Chrome DevTools

Open up DevTools to the Elements tab in Google Chrome and select the Reserve button.

In the same sidebar pane that includes Styles, Computed, and Layout is an option to open the Accessibility Tree. You may have to expand the menu in DevTools under the double arrow to find it.

The Accessibility Tree for the Reserve button.

The Accessibility Tree is a structure that is parallel to the DOM and represents accessibility information about the element currently selected in DevTools.

For our Reserve button, we can inspect that it has text content of “Reserve” and a role of “button”. If the button had an ARIA label, title or any other accessible name, it would show up here.

When we apply different CSS visibility techniques to the button, we can look at how the Accessibility Tree changes.

It’s a useful tool for troubleshooting issues that might be caused by a parent element further up the tree.

Video: An Overview of the Component Sandbox
Loaded: 3%
Current Time 0:00
/
Duration Time 3:10
Video Transcript

What I want to do before we really start diving in with code is give you a bit of a level set of some of the things that can affect keyboard access. So we've got all of our pages throughout our application. We also have kind of a hidden page here.

That's, it's linked in some of our readmes and things. But we have a special section of our site for kind of playing around with patterns that don't quite fit on a webpage. So if you're building a site, you know, maybe you've got an online style guide or someplace where you just sort of go and play with things that maybe the public doesn't really see, and that is our component sandbox.

So we'll come back to this a few times throughout the workshop for these really three different sections starting with CSS visibility techniques. And with this, we have a button it says reserve, and this button will be affected by these controls that we've got down here. So they're mostly CSS classes that apply CSS.

We do have one that applies an aria attribute. Since it's another hiding technique, I wanted you to be aware of it, but this button by default, it is focusable it is rendered. It is in the page. And if we inspect it in Chrome developer tools here, it is a focusable regular old button love those let's use them more.

Our div buttons are not real buttons, even though we can apply JavaScript, click events to them, buttons are superior for multiple reasons. They're focusable they give us the implicit button role by default, which we learned about in our semantics and ARIA workshop, they also respond to click events. So you can bind a single click event and you don't need to add keyboard events on top of it.

Yeah, buttons are awesome. So in Chrome dev tools, I'm kind of come over here to the accessibility tab and we can see the effect that these little controls, these radio buttons will have on our button. So our default state for including a button with, you know, let's see what kind of styles we've got on it.

It's got a color, a background color, you know, margins, padding, font styles, kind of the basics to reset from the way a button appears by default in our user agent or browser. But if we come back to the accessibility inspector, this tool, I love so much because it gives us a step like a status update on the accessibility situation for a given element.

And as a bit of a recap, the accessibility tree is a structure that sort of parallel to the DOM or document object model. Like we see over here on the left, the accessibility tree is a. The structure of only accessibility information. So which elements, you know, either built with, say the button element or a div with a roll of button on it.

Those can both impact what's in the accessibility tree. In this Chrome tool. We also have things like aria attributes, computed properties, and this accessible name, calculation viewer. So this button has text content of reserve. If it had an aria label or a title or aria-labeled-by or any of the other ways of adding an accessible name to a button that would show up here.

The Visually-hidden Technique

The first radio button applies a CSS class to button named visuallyHidden.

This is an arbitrary class that we added to our stylesheet.

It has a clip that gives it no dimensions, a height and width of 1px, border none, margin of -1px, no padding, absolute position so it’s not in the normal document flow, and overflow hidden.

It makes a useful utility class to add to your stylesheets. I always copy it from project to project!

Here’s the CSS:

.visuallyHidden {		
  clip: rect(0 0 0 0);
  height: 1px;
  width: 1px;
  border: none;
  margin: -1px;
  padding: 0;
  position: absolute;
  overflow: hidden;
}

When the visuallyHidden class is applied to the button, we can tell from the Accessibility Tree that it is still rendered. This means that screen readers will still be able to read it although it’s not really visible.

There are some situations where this technique comes in handy. We used it previously to add a visually-hidden heading that was pulled out of the layout.

Video: The Visually-hidden Technique
Loaded: 3%
Current Time 0:00
/
Duration Time 2:27
Video Transcript

But what's helpful to us is seeing what effect various CSS techniques have. And so often when I'm debugging something for keyboard accessibility, I use this tool a lot and sometimes it might be the element itself that I'm looking at to figure out, well, why isn't that? Why can't I reach or operate that button?

And sometimes I have to go up the tree, like the effect might be on a parent element somewhere. And so that's where this structure kind of visualization of the Dom and the accessibility tree can be so helpful because it will tell me what is going on here. So let's go through our controls. The first one we will apply to change it from its sort of default method is visually hidden.

we've seen this before. This is a CSS class that is arbitrary. It's something that we put into our style sheet. So we've got a visually hidden class in here. It has a clip of a rectangle with zero pixels top, right bottom left, going in the, the box model. So we've got a clip that gives it no dimensions, height, and width of one pixel board, or none negative one pixel margin, no padding position, absolute to pull it out of the regular flow of the document and overflow hidden.

So it takes that, element and it's technically rendering it. And we can tell that by looking at our accessibility tab, we still have all of this information here and it still has its contents. It still has a role of button. All of this stuff is still showing up. What happens is that the visually hidden class, it collapsed the space.

So it pulled it out of the flow as we saw at that position. Absolute. But it's still rendering it. So the text is still part of the accessibility tree and screen readers will still be able to read. But it's not focusable or really visible. So this is a technique that you might use for various scenarios.

We've seen it so far. If we wanted to add a, a heading, that's not shown visually, we've applied visually hidden to it for that case, even though headings are useful for everybody, sometimes you might have a use case for rendering something, but pulling it out layout. And so visually hidden can do that.

And that's a CSS class that I usually just copy from project to project. And it's a utility class that you can apply to things. So that's an important technique, but it obviously made it so that we can't see the button. We can't tab onto the button. So that's maybe not the technique we would be using in this case.

The Opacity Technique

When clicking the Opacity option, the space where our button was previously collapsed expands back out. The button is in the flow the document but we don’t see it.

Hitting the Tab key to move around, we can tell that there’s a tab stop but we can’t see where we are.

As you would imagine, setting the opacity of the button to zero means we don’t see it even though it’s still rendered.

Here’s the CSS for opacityNone:

opacityNone {
  opacity: 0;
}

When we look at it in the Accessibility tab, we can see a result similar to what we saw with visuallyHidden where accessibility information is shown. Except this time, the button’s visual space in the page is preserved.

The Accessibility Tree when opacity is set to zeroLoading

💡Tip

Opacity can be animated. See the lesson on Safe Animation with Reduced Motion for more info on accessible approaches to animation.

Video: The Opacity Technique
Loaded: 6%
Current Time 0:00
/
Duration Time 1:26
Video Transcript

So let's look at opacity. So when I clicked that the space jumped back out, like it, put it back into the flow of the document, but we don't see the button.

And if I tab, I actually do have a tab stop, but I don't see where I am. So with opacity. by taking it down to zero, like you would imagine we don't see the button, but it's still rendered. And so coming over to our accessibility tab, again, it's really similar to visually hidden, except that we reserved the space.

And so, you know, you might have a use case for having something rendered, but it's not affecting the layout or something. Opacity can also be animated. So some CSS properties can be eased and animated where some can not an entire CSS class, probably not a candidate for animation, but opacity, you can, you know, transition from zero to one and kind of get a fade effect.

Of course, we have talked about safe animation with reduced motion. That is a whole other topic, but opacity is one of those tools that you might have need in your toolbox, or you might find in a style sheet to go, well, why can't I see where I am? Or why am I getting, why am I focusing on a tab stop that I can't see.

You might find that it's something that has opacity zero that shouldn't because. You shouldn't really be able to focus on something that you can't see.

The Display Technique

The CSS display: none; technique is a big hammer that hides the element from everybody in every context.

Sometimes that’s the tool you want!

When we apply the displayNone class to the button and look in the Accessibility Tree, it says “Accessibility node not exposed” and “Element is not rendered”.

The Accessibility Tree with display: none appliedLoading

The visual space is also collapsed and you can’t see it.

We saw this earlier in the example of the dropdown that wasn’t reachable. It used display: none; on the unordered list element that kept us from focusing on items that shouldn’t have been Tabbable.

One interesting fact is that you can still use aria-labelledby to reference an element with display: none; applied to it.

Video: The Display Technique
Loaded: 6%
Current Time 0:00
/
Duration Time 1:18
Video Transcript

So next is display display, none. And this is the big hammer that you use to just hide it from everybody, everybody in every context, sometimes that's the tool you want.

So in our accessibility inspector, it says accessibility node not exposed. Element is not rendered so far. We've seen things that are rendered, but maybe not. You can't see with your eyeballs display, none hides it from everyone. You don't see it. It collapses the space. It's not rendered in the accessibility tree.

And so that might be a technique, you know, if you need something it's in the page somewhere but you're not using it right then. Like you don't want it to take focus. You don't want it to be read aloud in a screen reader. There are, of course, times when display none is useful. We saw one example of that in our little dropdown, when that dropdown was not expanded, the UL had display none on it, which kept us from focusing on the items that we shouldn't be able to focus on.

So one kind of interesting thing about display. None is that. You can reference elements that have displayed on, on them using aria labeled by kind of a, an interesting trivia. So if something is not rendered, you can still reference it with aria labeled by kind of a quirky detail. So yeah, display none that one's important to know

The Visibility Technique

Applying CSS visibility: hidden; to an element is another interesting hiding technique that is kind of like a combination of the others.

It preserves the space while visually hiding an element like the opacity method did, so there’s a jump when switching over from the display: none; technique. However, this time the Accessibility Tree doesn’t have any information to show.

Screen readers will typically not read elements with visibility: hidden; applied (but you should always test to make sure). You also can’t focus on them.

This is a good technique if you don’t want something affect your layout but it’s irrelevant for a screen reader to read aloud.

Video: The Visibility Technique
Loaded: 8%
Current Time 0:00
/
Duration Time 1:04
Video Transcript

Visibility hidden is a really interesting one.

So this one, it's almost like a combination of the others, so it, it reserved the space. So when we went from display none to visibility hidden, you see that jump. So we're reserving the space. We don't see it. So it has that effect kind of like opacity but unlike opacity, which still renders, you know, to the accessibility tree visibility hidden does not.

So it reserves the space and the layout, but it keeps screen readers from reading it aloud and it's not focusable so sometimes visibility hidden might be the tool that you want. Like if you don't want to affect layout, but you've got something that's not relevant to screen reader, users or keyboard users.

Yeah, it's nice to have these tools at your disposal and to know about them because they will all come up even if you don't, you yourself don't necessarily have a use case for it right away. You might find it in a style sheet and it's helpful to know what effects these have on interactions. So visibility hidden is a useful one.

The aria-hidden Technique

The aria-hidden technique isn’t a CSS approach but I’m including it here since it is an element hiding technique that you should be familiar with.

When you apply aria-hidden="true" to an element or its parent element, it will remove accessibility information from the element or HTML subtree to which it has been applied.

Notice that the button is still visible on the page.

If a screen reader is able to focus on a tab stop that doesn’t have accessibility information, it can cause what is known as a ghost control. It can be quite confusing! Chrome has evolved in this scenario, where the element is aria-hidden but still focusable, to render it with accessibility information anyway.

If you really want to hide something that has the aria-hidden attribute, you also need to add tabindex="-1" on an interactive control to remove it from the tab order. This combination will also suppress screenreader output in Chrome. On its own, aria-hidden="true" affects screen readers and not the keyboard.

As far as the Accessibility Tree goes, it’s kind of in a weird in-between state. It reports that the element is focusable which is technically true, but it would require JavaScript to execute. Hitting the Tab key on the keyboard skips past the button with the tabindex set to -1.

The Accessibility Tree when aria-hidden is appliedLoading

The big takeaway here is that you should always test manually with the keyboard and screen readers, no matter what a dev tool says!

Video: The aria-hidden Technique
Loaded: 3%
Current Time 0:00
/
Duration Time 3:08
Video Transcript

We have one more here of aria hidden. So this isn't really a CSS class. This is an aria attribute of aria dash hidden of true. So this one is adding an aria state to a button. So right now I've got it on a button itself. It could be applied to a parent element. And as we'll see with ARIA hidden that can be a bit of a gotcha.

So what aria hidden does can come back here to our button. It it actually will typically remove the accessibility information from a button or any part of an HTML subtree what's happening here in Chrome. They've tried to fix an issue that comes up where this element is still focusable, but aria hidden would otherwise strip away its accessibility information.

So when a screen reader, if we focus on something that doesn't have accessibility information, it causes what's called a ghost control. So what Chrome is trying to do here is. Say, well, this thing is focusable it's hidden, hidden of true, but we're going to render it anyway because we want screen reader users to not be given this ghost control.

So if we really wanted to hide it from everyone, we would have to go one step further and add tab index of negative one. So that will remove it from the tab order. And the combination of ARIA hidden of true and tab index of negative one should kind of remove it from screenreader output in Chrome, in this accessibility inspector, it's still kind of a weird like in-between state.

Like it still says focusable true. And that's technically true. It's focusable with JavaScript right now. But if I tab through here, we skipped by that button. It's not keyboard focusable. And so Chrome's dev, this is like a case where the computed properties here kind of give you a really confusing situation.

What I wanted to show you really is that aria hidden is another hiding technique that it can affect the screen reading experience. Like if you are debugging a page, like let's say I had aria hidden up here on a parent element. It could say aria hidden of true. So now it says accessibility node not exposed element is already hidden because this is not a focusable element.

Chrome's like, all right, we'll hide it. But then the button they were trying to help us. Right? So they give us this kind of weird, like half rendered, but they say it's hidden, but it's focusable but it's not like the only really way that the way to know what's going on. Sometimes the tool just makes things confusing, just test it and test it with the keyboard.

Like if I tab through here, I can't reach it. So that's pretty clear, like the Chrome dev tools thing, if it's confusing, just, just close it, use the keyboard to test it, fire up a screen reader to test it, see what happens. So sometimes the tooling it's helpful, but if you're like, what is this even saying?

You know, it's kind of contradicting itself. Remember we want to put our manual testing hats on and really test with our tab key. And as we'll see a little bit later, we'll fire up screen readers and see what effects some of these things have there.

Debugging Visibility Issues

If you find yourself in a situation where you can’t see where you are on the page or you can’t operate a control, check out the CSS in DevTools.

There’s also an option in the Styles pane of DevTools to force element states.

Browsers have created these options to visualize specific states for keyboard and mouse users. If a mouse user clicks something, they usually don’t want to see a persistent focus outline. On the other hand, a keyboard user needs that focus style.

Because of the box of spiders that the focus pseudo-selector implementation has been historically for mouse users, a new focus-visible pseudo-selector was created for keyboard users. Focus-visible uses heuristics to apply focus styles more intelligently for keyboard interactions where focus couldn’t be updated or adapted.

Click the :hov option, then select :focus and :focus-visible to force the element to be activated for both scenarios.

focus and focus-visible in the Styles pane of DevToolsLoading

If you toggle both options on and off and still don’t see a focus outline, you know that keyboard users likely won’t see where they are on the page.

Video: Debugging Visibility Techniques
Loaded: 36%
Current Time 0:00
/
Duration Time 2:03
Video Transcript

So we've got these various techniques especially the CSS ones as you're debugging things.

I mean, Ari hidden will come up too, but aria hidden on its own will not affect the keyboard. It will affect screen reader. Which is sometimes why it can get a little bit messed up it's folks use it and they don't test it with a screen reader, but we always want to be testing with the keyboard. And so having these visibility techniques in your back pocket can be really helpful because you have to figure out, okay, well, why can I not see where I am on the screen?

Why can I not operate this control? go debugging in the dev tools and go and check out what CSS is applied.

One other thing I'll bring to your attention. I'll open the dev tools back up and come onto our button here. Another debugging tool. I will mention since we're talking about keyboard support and kind of like trying to figure out why something isn't working right for a button right now, we're back to our default, you know, no weirdness applied in the Chrome developer tools.

There is this option right here. It says, colon HOV for hover. And you get this little force element state panel. And we've used this quite a bit throughout the workshops so far, but this is super helpful to come in here and force the elements, state on something. We've got focus visible over here too. So focus visible uses more. What we call heuristics, it's actually checking is the user clicking with a mouse or are they tabbing with the keyboard? And we can kind of mimic that with this force element state. So if I come in here and I click on the button, I don't see a focus style, but if I tab onto it, I do.

So that's some of the differences between focus and focus visible by clicking. We actually do technically focus on the element, but I don't see a focus outline unless I operate the keyboard kind of an interesting approach. It's really helpful. Cause it used to be what I call button focus hell. And it was really hard to work with before.

So lots of debugging tips, lots of Chrome dev tools and Firefox dev tools. And those are really important for when you're doing stuff for keyboard support.